# ----------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License
# ----------------------------------------------------------------------
"""Contains the TypeInfoFactory object"""

import os

import CommonEnvironment
from CommonEnvironment import Interface

# ----------------------------------------------------------------------
_script_fullpath                            = CommonEnvironment.ThisFullpath()
_script_dir, _script_name                   = os.path.split(_script_fullpath)
#  ----------------------------------------------------------------------

# ----------------------------------------------------------------------
class TypeInfoFactory(Interface.Interface):
    """Creates constructs useful when generating code for a specific type"""

    # ----------------------------------------------------------------------
    # |
    # |  Public Types
    # |
    # ----------------------------------------------------------------------
    class Result(object):
        """Result information about a type when it is used in various scenarios."""

        # ----------------------------------------------------------------------
        def __init__(self, parameter_decl, validation_statements, invocation_statements):
            self.ParameterDecl              = parameter_decl
            self.ValidationStatements       = validation_statements
            self.InvocationStatements       = invocation_statements

        # ----------------------------------------------------------------------
        def __repr__(self):
            return CommonEnvironment.ObjectReprImpl(self)

    # ----------------------------------------------------------------------
    # |
    # |  Public Properties
    # |
    # ----------------------------------------------------------------------
    @Interface.abstractproperty
    def TypeName(self):
        """Name of the type"""
        raise Exception("Abstract property")

    @Interface.abstractproperty
    def CppType(self):
        """C++ type"""
        raise Exception("Abstract property")

    # ----------------------------------------------------------------------
    # |
    # |  Public Methods
    # |
    # ----------------------------------------------------------------------
    def __init__(
        self,
        custom_structs=None,
        custom_enums=None,
        member_type=None,
        create_type_info_factory_func=None,
    ):
        # By default, custom structs are not used or preserved. Custom overridden
        # factories may use this information.
        pass

    # ----------------------------------------------------------------------
    def __repr__(self):
        return CommonEnvironment.ObjectReprImpl(self)

    # ----------------------------------------------------------------------
    @staticmethod
    @Interface.abstractmethod
    def GetInputInfo(arg_name, is_optional, invocation_template):
        """\
        Returns information about the type when used as an input argument.

        `invocation_template` is a template string that should be formatted with
        the argument values.
        """
        raise Exception("Abstract method")

    # ----------------------------------------------------------------------
    @staticmethod
    @Interface.abstractmethod
    def GetInputBufferInfo(arg_name, is_optional, invocation_template):
        """\
        Returns information about the type when used as a buffer input argument.

        `invocation_template` is a template string that should be formatted with
        the argument values.
        """
        raise Exception("Abstract method")

    # ----------------------------------------------------------------------
    @staticmethod
    @Interface.abstractmethod
    def GetOutputInfo(
        arg_name,
        result_name="result",
        is_struct_member=False,
    ):
        """\
        Returns information about the type when used as an output argument.

        `result_name` is the name of the result returned by the shared library.
        """
        raise Exception("Abstract method")

    # ----------------------------------------------------------------------
    @staticmethod
    @Interface.abstractmethod
    def GetDestroyOutputInfo(
        arg_name="result",
    ):
        """\
        Returns information about the type when data generated by `GetOutputInfo` needs
        to be deleted by the caller.

        Return `None` if no explicit destruction functionality is required.
        """
        raise Exception("Abstract method")
